<!--
	作者：2575202388@qq.com
	时间：2018-11-12
	描述：前端导出电子表格组件
-->
<template>
	<div>
		<Modal v-model="modal" :title="title" @on-cancel="oncancel" @on-visible-change="onvisiblechange" @on-ok="onok">
			<div ref="body">
				<Row style="margin-bottom:10px;line-height: 30px;">
					<Col span="3">
					<label>导出类型</label>
					</Col>
					<Col span="9">
					<Select size="small" filterable v-model="exporttype" style="width: 87%;">
						<Option :value="1" label="导出已选中数据" />
						<Option :value="2" label="自定义导出数据" />
					</Select>
					</Col>
					<Col span="12">
					<Col span="6"><label>文件名称</label></Col>
					<Col span="18">
					<Input size="small" placeholder="请输入即将导入的文件名" v-model="fileName" />
					</Col>
					</Col>
				</Row>

				<Row v-if="zdylx" style="margin-bottom:10px;line-height: 30px;">
					<Col span="3">
					<label>开始位置</label>
					</Col>
					<Col span="9">
					<Select size="small" filterable v-model="startP" style="width: 87%;">
						<Option :value="intem.value" :disabled="intem.disabled" :label="intem.label" v-for="intem in slist" />
					</Select>
					</Col>

					<Col span="3">
					<label>结束位置</label>
					</Col>
					<Col span="9">
					<Select size="small" filterable v-model="endP">
						<Option :value="intem.value" :disabled="intem.disabled" :label="intem.label" v-for="intem in elist" />
					</Select>
					</Col>
				</Row>

				<Transfer :data="headerlist" :titles="titles" :target-keys="targetKeys" @on-change="handleChange" style="margin-left: 35px;"></Transfer>

				<Divider orientation="center" style="font-size: 12px;">导出详情</Divider>
				<div style="width: 100%;height: auto;">
					<Row>
						<label>导出文件名：</label>
						<span>{{this.fileName}}.xlsx</span>
					</Row>
					<Row>
						<label>导出数据条数：</label>
						<span>{{totalcount}}（条）</span>
					</Row>
					<Row>
						<label>导出数据范围：</label> 第
						<span>{{startP*pagesize}}</span>（条） ~ 第
						<span>{{endP*pagesize>total?total:endP*pagesize}}</span>（条）
					</Row>
					<Row>
						<label>表头字段：</label>
						<span>
							<Tag closable @on-close="tagclose(index)" v-for="(item,index) in taplist">{{item.label}}</Tag>
						</span>
					</Row>
				</div>
			</div>

			<div slot="footer">
				<Button type="text" @click="modal=false">取消</Button>
				<Button type="primary" @click="onok">开始导出</Button>
			</div>

			<transition>
				<div v-if="loading" :style="loadstyle">
					<i-circle :percent="percent" :stroke-color="color" :style="circlestyle">
						<Icon v-if="loadstatus==1" type="ios-checkmark" size="60" style="color:#5cb85c"></Icon>
						<Icon v-if="loadstatus==-1" type="ios-close" size="60" style="color:#ff5500"></Icon>
						<span v-if="loadstatus==0" style="font-size:24px">{{ percent }}%</span>
					</i-circle>
					<div style="text-align: center;">
						{{loadtext}}
					</div>
				</div>
			</transition>
		</Modal>
	</div>
</template>

<script>
	import excel from "js-export-excel"

	export default {
		name: "Exportexcel",
		props: {
			title: {
				type: String,
				default: "excel数据导出"
			},
			exportfileName: {
				type: String,
				default: "导出excel文件"
			},
			headerlist: {
				type: Array,
				default: function() {
					return [];
				}
			},
			selectData: {
				type: Array,
				default: function() {
					return [];
				}
			},
			defaultheader: {
				type: Array,
				default: function() {
					return [];
				}
			},
			total: {
				type: Number,
				default: function() {
					return 0;
				}
			},
			pagesize: {
				type: Number,
				default: function() {
					return 0;
				}
			},
			serverUrl: {
				type: String,
				default: ""
			},
			paramiters: {
				type: Object,
				default: function() {
					return {};
				}
			},
		},
		data() {
			return {
				hlist: {},
				loadtext: "",
				modal: false,
				exporttype: -1,
				targetKeys: [],
				widths: [],
				startP: 0,
				loading: false,
				loadstatus: 0,
				zdylx: false,
				endP: 1,
				percent: 0,
				fileName: "",
				titles: ["可导出字段", "已选导出字段"],
				loadstyle: {
					position: "absolute",
					top: "51px",
					width: "500px",
					background: "rgba(255,255,255,.9)"
				},
				circlestyle: {
					"margin-left": "190px",
				},
				timer: null,
				slist: [],
				elist: []

			}
		},
		methods: {
			handleChange(newTargetKeys, direction, moveKeys) {
				this.targetKeys = newTargetKeys;
			},
			open() {
				this.loading = false;
				this.modal = true;
			},
			close() {
				this.modal = false;
			},
			oncancel() {
				this.$emit("on-cancel");
			},
			onok() {
				if(this.targetKeys.length == 0) {
					this.$Message.warning({
						content: "导出字段不能为空"
					});
				} else {
					this.getdatas();
				}
				this.$emit("on-ok");
			},
			onvisiblechange(v) {
				this.$emit("on-visible-change", v);
			},
			tagclose(index) {
				this.targetKeys.splice(index, 1);
			},
			getparams(offset) {
				return {
					_PAGE_NO_: this.startP + offset + 1,
					_PAGE_SIZE_: this.pagesize,
					...this.paramiters
				};
			},
			getdatas() {

				if(this.exporttype == 1) {
					if(this.selectData.length > 0) {
						this.startload();
						this.genaraterExcel(this.selectData);
						this.pcomplete();
					} else {
						this.$Message.warning({
							content: "未选中任何数据"
						});
					}
				} else {
					this.startload();
					this.$http.all(this.gethttps())
						.then(this.$http.spread((...result) => {
							var _datas = [];
							if(result) {
								result.forEach(value => {
									if(value.code == "0000") {
										_datas = [..._datas, ...value.data.data]
									}
								});
							}
							this.genaraterExcel(_datas);
							this.pcomplete();
						}))
						.catch((info, err) => {
							this.perror();
						});
				}
			},
			gethttps() {
				var https = [];
				let size = Math.ceil(this.totalcount / this.pagesize);
				for(let index = 0; index < size; index++) {
					https.push(this.$http.post(this.serverUrl, this.getparams(index)))
				}
				return https;
			},
			startload() {
				this.loading = true;
				let height = this.$refs.body.offsetHeight + 30;
				this.loadstyle.height = height + "px";
				this.circlestyle["margin-top"] = height / 2 - 50 + "px";
				this.ploading();
			},
			ploading() {
				this.loadtext = "处理载中,请稍后...";
				this.timer = setInterval(() => {
					this.percent += 2;
					if(this.percent == 90) {
						clearInterval(this.timer);
					}
				}, 100);
			},
			genaraterExcel(data) {
				var option = {};
				option.fileName = this.fileName;
				option.datas = [{
					sheetData: this.getexceldatajson(data),
					sheetHeader: this.getexcelhead(data[0]),
					columnWidths: this.widths
				}];
				var toExcel = new excel(option);
				toExcel.saveExcel();
			},
			getexcelhead(hlist) {
				var hl = [];
				if(hlist) {
					this.targetKeys.map(key => {
						hl.push(this.hlist[key]);
					});
				}
				return hl;
			},
			getexceldatajson(data) {
				var list = [];
				if(data) {
					data.forEach(value => {
						var _data = {};
						this.targetKeys.forEach(key => {
							_data[key] = value[key];
						});
						list.push(_data);
					});
				}
				return list;
			},
			pcomplete() {
				if(this.timer) {
					clearInterval(this.timer);
				}
				this.percent += (100 - this.percent);
				this.loadtext = "导出成功";
				this.loadstatus = 1;
				setTimeout(() => {
					this.loading = false;
					this.percent = 0;
					this.loadstatus = 0;
				}, 1500);
			},
			perror(msg) {
				if(this.timer) {
					clearInterval(this.timer);
				}
				this.loadtext = msg || "导出失败";
				this.loadstatus = -1;
				setTimeout(() => {
					this.loading = false;
					this.percent = 0;
					this.loadstatus = 0;
				}, 1500);
			},
			getpagelist() {
				var _data = [];
				var _edata = [];
				let size = Math.ceil(this.total / this.pagesize);
				for(let index = 0; index <= size; index++) {

					var count = ((index * this.pagesize) == 0 ? 1 : index * this.pagesize);
					if(index == size && count > this.total) {
						count = this.total;
					}

					var _d = {
						value: index,
						label: "第" + count + "条",
						disabled: false
					};
					var sd = { ..._d,
					};
					var ed = { ..._d
					};
					if(index == 0) {
						ed.disabled = true;
					} else if(index == size) {
						sd.disabled = true;
					}
					_data.push(sd);
					_edata.push(ed);
				}
				this.slist = _data;
				this.elist = _edata;
			}
		},
		created() {
			this.fileName = this.exportfileName;
			this.targetKeys = this.defaultheader;
			this.getpagelist();
			this.exporttype = 2;
			this.headerlist.forEach(value => {
				this.hlist[value.key] = value.label;
			});
		},
		computed: {
			color() {
				let color = '#2db7f5';
				if(this.loadstatus == 1) {
					color = '#5cb85c';
				} else if(this.loadstatus == -1) {
					color = '#ff5500';
				}
				return color;
			},
			taplist() {
				var list = [];
				this.widths = [];
				this.headerlist.forEach(value => {
					if(this.targetKeys.includes(value.key)) {
						list.push({ ...value
						});
						this.widths.push(value.width || 8);
					}
				});
				return list;
			},
			totalcount() {
				var count = 0;
				if(this.exporttype == 1) {
					count = this.selectData.length;
				} else {
					count = this.endP - this.startP;
				}
				count = this.pagesize * count;

				if(this.endP == (Math.ceil(this.total / this.pagesize))) {
					var d = this.total - this.pagesize * this.startP;
					if((d - count) < 0) {
						count = d;
					};
				}
				if(count > this.total) {
					count = this.total;
				}
				return count;
			}
		},
		watch: {
			exporttype: function(v) {
				if(v == 2) {
					this.targetKeys = [];
					this.zdylx = true;
				} else {
					this.targetKeys = this.defaultheader;
					this.zdylx = false;
				}
			},
			pagesize: function(v) {
				setTimeout(() => {
					this.getpagelist();
				}, 200);
			},
			total: function(v) {
				setTimeout(() => {
					this.getpagelist();
				}, 200);
			},
			startP: function(v) {
				this.elist.map((value, _index) => {
					if(_index <= v) {
						value.disabled = true;
					} else {
						value.disabled = false;
					}
					return value;
				});
				if(!this.endP) {
					this.endP = v + 1;
				} else if(this.endP <= v) {
					this.endP = v + 1;
				}
			}
		}
	}
</script>

<style>

</style>